import React, { useContext, Dispatch } from 'react';
import { Row, Col } from 'antd';
import { OptionData } from 'rc-select/lib/interface';

import { QueryContext } from '../../store';
import { JsonPathRule, Config, JsonGroup, Action } from '../../types';
import styles from '../../styles.less';
import RuleDrag from '../rule/RuleDrag';
import RuleFields from '../rule/RuleFields';
import RuleOperators from '../rule/RuleOperators';
import RuleInput from '../rule/RuleInput';
import RuleActions from '../rule/RuleActions';

const Rule: React.FC<{
  rule: JsonPathRule,
  config: Config,
  path: string
}> = (props) => {
  const { rule, config, path } = props;
  const { dispatch } = useContext<{ state: JsonGroup; dispatch: Dispatch<Action> }>(QueryContext);

  const renderDel = () => {
    if (config.settings.readonly || !config.settings.showDelRule) return void 0;
    return (
      <Col flex="none">
        <RuleActions
          config={config}
          path={path}
          onClick={(action) => dispatch(action)}
        />
      </Col>
    );
  }

  const renderInput = () => {
    if (typeof config.fields === "undefined") return void 0;
    const fields = config.fields[rule.field as string];
    if (typeof fields === "undefined") return void 0;
    if (!rule.operator) return void 0;
    const nb_input = config.operators[rule.operator as string].nb_input;
    if (nb_input == 0) return void 0;
    return (
      <Col flex="auto">
        <RuleInput config={config} rule={rule} />
      </Col>
    );
  }

  const renderOperators = () => {
    if (typeof config.fields === "undefined") return void 0;
    const fields = config.fields[rule.field as string];
    if (typeof fields === "undefined") return void 0;
    const options: OptionData[] = [];
    Object.keys(config.operators).forEach((operator, index) => {
      if (config.operators[operator].apply_to.findIndex((value) => value == fields.type) != -1) {
        options.push({ key: index, label: config.operators[operator].label, value: operator });
      }
    });
    return (
      <Col flex="120px">
        <RuleOperators
          className={styles.operators}
          config={config}
          options={options}
          operator={rule.operator}
          path={path}
          onChange={(action) => dispatch(action)}
        />
      </Col>
    );
  }

  const renderFields = () => {
    const options: OptionData[] = [];
    config.fields && Object.keys(config.fields).forEach((field, index) => {
      const fieldInfo = config.fields ? config.fields[field] : void 0;
      if (fieldInfo) {
        options.push({ key: index, label: fieldInfo.label, value: fieldInfo.value });
      }
    })
    return (
      <Col flex="120px">
        <RuleFields
          className={styles.field}
          config={config}
          options={options}
          field={rule.field}
          path={path}
          onChange={(action) => dispatch(action)}
        />
      </Col>
    );
  }

  const renderDrag = () => {
    if (config.settings.readonly || !config.settings.showDrag) return void 0;
    return (
      <Col>
        <RuleDrag />
      </Col>
    );
  }

  return (
    <div className={styles.rule}>
      <Row gutter={[8, 8]} justify="space-between" wrap={false}>
        <Col flex="auto">
          <Row gutter={[8, 8]} wrap={false} align="top">
            {renderDrag()}
            {renderFields()}
            {renderOperators()}
            {renderInput()}
          </Row>
        </Col>
        {renderDel()}
      </Row>
    </div>
  );
}

export default Rule;
